
open GL
open Glu
open Glut

(* TODO move to config *)
let timerTicks = 50

let in_channel = ref (Obj.magic 0)
let out_channel = ref (Obj.magic 0)
let buffer = String.create (1024*1024)

let send string = 
	let () = output_string !out_channel 
		(Types.Data.show (Types.Data.String string) ^ "\n") in
	let () = flush !out_channel in
	()
let recv () = 
	let line = input_line !in_channel in
	Types.Data.read line

let display () = 
    glClear [GL_COLOR_BUFFER_BIT];
    glBegin GL_LINE_LOOP;
    glColor4 1.0 1.0 1.0 1.0;
    glVertex2 (1.0) (1.0);
    glVertex2 (1.0) (0.0);
    glVertex2 (0.0) (0.0);
    glVertex2 (0.0) (1.0);
    glEnd ();
	(* This should *not* be here *)
	let () = send "getObjects" in
	let objects = recv () in
	let () = match objects with
	| Types.Data.List ls -> List.iter Object.draw ls
	| _ -> assert false
	in let () = send "getPlayers" in
	let players = recv () in
	let () = match players with
	| Types.Data.List ls -> List.iter Player.draw ls
	| _ -> assert false
	in glutSwapBuffers ()

let finalize () = 
	let () = Unix.shutdown_connection !in_channel in
    ()

let keyboard ~key ~x ~y = begin match key with
    | '\027' | 'q' -> let () = finalize () in exit 0
    | ' ' -> glutPostRedisplay ()
    | _ -> ()
    end

let special ~key ~x ~y = 
	match key with
	| GLUT_KEY_UP    -> let () = send "+Up"    in let _ = recv () in () 
	| GLUT_KEY_LEFT  -> let () = send "+Left"  in let _ = recv () in () 
	| GLUT_KEY_RIGHT -> let () = send "+Right" in let _ = recv () in () 
	| GLUT_KEY_DOWN  -> let () = send "+Down"  in let _ = recv () in ()
	| _ -> ()
let special_up ~key ~x ~y = 
   	match key with
	| GLUT_KEY_UP    -> let () = send "-Up"    in let _ = recv () in () 
	| GLUT_KEY_LEFT  -> let () = send "-Left"  in let _ = recv () in () 
	| GLUT_KEY_RIGHT -> let () = send "-Right" in let _ = recv () in () 
	| GLUT_KEY_DOWN  -> let () = send "-Down"  in let _ = recv () in ()
	| _ -> ()

let rec timer ~value = 
    glutTimerFunc timerTicks timer 0;
    glutPostRedisplay ();
    ()

let reshape ~width ~height = 
    glViewport 0 0 width height;
    glMatrixMode GL_PROJECTION;
    glLoadIdentity ();
    let length = float (min width height) in
    let fwidth = float width /. length in
    let fheight = float height /. length in
    glOrtho 0.0 fwidth 0.0 fheight (-1.0) (1.0);
    glTranslate (fwidth /. 2.0 -. 0.5) (fheight /. 2.0 -. 0.5) 0.0;
    glMatrixMode GL_MODELVIEW;
    ()

let initGL () = 
    glClearColor 0.0 0.0 0.0 1.0;
    glShadeModel GL_FLAT;
    glPointSize 2.5;
    glEnable GL_BLEND;
    glBlendFunc Sfactor.GL_SRC_ALPHA Dfactor.GL_ONE_MINUS_SRC_ALPHA;
    glHint GL_LINE_SMOOTH_HINT GL_DONT_CARE;
    glHint GL_POINT_SMOOTH_HINT GL_DONT_CARE;
    reshape 800 600;
    ()

let initGlut () = 
    ignore (glutInit Sys.argv);
    glutInitDisplayMode [GLUT_DOUBLE; GLUT_RGBA];
    glutInitWindowSize 800 600;
    ignore (glutCreateWindow "gra");
    initGL ();
    glutDisplayFunc ~display;
    glutReshapeFunc ~reshape;
    glutKeyboardFunc ~keyboard;
    glutSpecialFunc ~special;
    glutSpecialUpFunc ~special_up;
    glutTimerFunc timerTicks timer 0;
    ()

let openConnection server port = 
	let ip = (Unix.gethostbyname server).Unix.h_addr_list.(0) in
	let addr = Unix.ADDR_INET(ip, port) in
	let inc, outc = Unix.open_connection addr in
	let () = in_channel := inc in
	let () = out_channel := outc in
	()

let main () = 
	openConnection (Sys.argv.(1)) (Config.port_number);
    initGlut ();
    glutMainLoop ();
    ()

let () = main ()

